#ifndef __OCPP_CesiumCartesian4_H__
#define __OCPP_CesiumCartesian4_H__

#include "Spherical.h"

namespace OCPP
{
	namespace Cesium
	{
		class _CesiumExport Cartesian4
		{
		public:
			double x, y, z, w;
			Cartesian4(double _x = 0.0, double _y = 0.0, double _z = 0.0, double _w = 0.0)
				: x(_x)
				, y(_y)
				, z(_z)
				, w(_w)
			{

			}

			Cartesian4& operator = (const Cartesian4& fScaler)
			{
				return (Cartesian4&)*this;
			}

			/**
			 * Creates a Cartesian4 instance from x, y, z and w coordinates.
			 *
			 * @param {number} x The x coordinate.
			 * @param {number} y The y coordinate.
			 * @param {number} z The z coordinate.
			 * @param {number} w The w coordinate.
			 * @param {Cartesian4} [result] The object onto which to store the result.
			 * @returns {Cartesian4} The modified result parameter or a new Cartesian4 instance if one was not provided.
			 */
			static Cartesian4 fromElements(double x, double  y, double  z, double  w) {
				Cartesian4 result;
				result.x = x;
				result.y = y;
				result.z = z;
				result.w = w;
				return result;
			};

			/**
			 * Creates a Cartesian4 instance from a {@link Color}. <code>red</code>, <code>green</code>, <code>blue</code>,
			 * and <code>alpha</code> map to <code>x</code>, <code>y</code>, <code>z</code>, and <code>w</code>, respectively.
			 *
			 * @param {Color} color The source color.
			 * @param {Cartesian4} [result] The object onto which to store the result.
			 * @returns {Cartesian4} The modified result parameter or a new Cartesian4 instance if one was not provided.
			 */
			 //static Cartesian4 fromColor(color) {
			 //    Cartesian4 result;
			 //    result.x = color.red;
			 //    result.y = color.green;
			 //    result.z = color.blue;
			 //    result.w = color.alpha;
			 //    return result;
			 //};

			 /**
			  * The number of elements used to pack the object into an array1.
			  * @type {number}
			  */
			const static int packedLength = 4;

			/**
			 * Stores the provided instance into the provided array1.
			 *
			 * @param {Cartesian4} value The value to pack.
			 * @param {number[]} array1 The array1 to pack into.
			 * @param {number} [startingIndex=0] The index into the array1 at which to start packing the elements.
			 *
			 * @returns {number[]} The array1 that was packed into
			 */
			static DoubleVector pack(Cartesian4 value, DoubleVector array1, size_t startingIndex = 0) {
				array1[startingIndex++] = value.x;
				array1[startingIndex++] = value.y;
				array1[startingIndex++] = value.z;
				array1[startingIndex] = value.w;
				return array1;
			};

			/**
			 * Retrieves an instance from a packed array1.
			 *
			 * @param {number[]} array1 The packed array1.
			 * @param {number} [startingIndex=0] The starting index of the element to be unpacked.
			 * @param {Cartesian4} [result] The object into which to store the result.
			 * @returns {Cartesian4}  The modified result parameter or a new Cartesian4 instance if one was not provided.
			 */
			static Cartesian4 unpack(DoubleVector array1, size_t startingIndex = 0) {
				Cartesian4 result;
				result.x = array1[startingIndex++];
				result.y = array1[startingIndex++];
				result.z = array1[startingIndex++];
				result.w = array1[startingIndex];
				return result;
			};

			/**
			 * Flattens an array1 of Cartesian4s into an array1 of components.
			 *
			 * @param {Cartesian4[]} array1 The array1 of cartesians to pack.
			 * @param {number[]} [result] The array1 onto which to store the result. If this is a typed array1, it must have array1.size() * 4 components, else a {@link DeveloperError} will be thrown. If it is a regular array1, it will be resized to have (array1.size() * 4) elements.
			 * @returns {number[]} The packed array1.
			 */
			DoubleVector packArray(std::vector<Cartesian4> array1) {
				auto length = array1.size();
				auto resultLength = length * 4;
				DoubleVector result;
				result.resize(resultLength);

				for (auto i = 0; i < length; ++i) {
					Cartesian4::pack(array1[i], result, i * 4);
				}
				return result;
			};

			/**
			 * Unpacks an array1 of cartesian components into an array1 of Cartesian4s.
			 *
			 * @param {number[]} array1 The array1 of components to unpack.
			 * @param {Cartesian4[]} [result] The array1 onto which to store the result.
			 * @returns {Cartesian4[]} The unpacked array1.
			 */
			std::vector<Cartesian4> unpackArray(DoubleVector array1) {
				auto length = array1.size();

				std::vector<Cartesian4> result;
				result.resize(length / 4);

				for (auto i = 0; i < length; i += 4) {
					auto index = i / 4;
					result[index] = Cartesian4::unpack(array1, i);
				}
				return result;
			};

			/**
			 * Creates a Cartesian4 from four consecutive elements in an array1.
			 * @function
			 *
			 * @param {number[]} array1 The array1 whose four consecutive elements correspond to the x, y, z, and w components, respectively.
			 * @param {number} [startingIndex=0] The offset into the array1 of the first element, which corresponds to the x component.
			 * @param {Cartesian4} [result] The object onto which to store the result.
			 * @returns {Cartesian4}  The modified result parameter or a new Cartesian4 instance if one was not provided.
			 *
			 * @example
			 * // Create a Cartesian4 with (1.0, 2.0, 3.0, 4.0)
			 * const v = [1.0, 2.0, 3.0, 4.0];
			 * const p = Cesium.Cartesian4.fromArray(v);
			 *
			 * // Create a Cartesian4 with (1.0, 2.0, 3.0, 4.0) using an offset into an array1
			 * const v2 = [0.0, 0.0, 1.0, 2.0, 3.0, 4.0];
			 * const p2 = Cesium.Cartesian4.fromArray(v2, 2);
			 */
			static Cartesian4 fromArray(DoubleVector array1, size_t startingIndex = 0)
			{
				return Cartesian4::unpack(array1, startingIndex);
			}

			/**
			 * Computes the value of the maximum component for the supplied Cartesian.
			 *
			 * @param {Cartesian4} cartesian The cartesian to use.
			 * @returns {number} The value of the maximum component.
			 */
			static Cartesian4 maximumComponent(Cartesian4 cartesian) {
				return (std::max)(cartesian.x,
					(std::max)(cartesian.y,
						(std::max)(cartesian.z, cartesian.w)));
			};

			/**
			 * Computes the value of the minimum component for the supplied Cartesian.
			 *
			 * @param {Cartesian4} cartesian The cartesian to use.
			 * @returns {number} The value of the minimum component.
			 */
			static double minimumComponent(Cartesian4& cartesian) {
				return (std::min)(cartesian.x,
					(std::min)(cartesian.y, (std::min)(cartesian.z, cartesian.w)));
			};

			/**
			 * Compares two Cartesians and computes a Cartesian which contains the minimum components of the supplied Cartesians.
			 *
			 * @param {Cartesian4} first A cartesian to compare.
			 * @param {Cartesian4} second A cartesian to compare.
			 * @param {Cartesian4} result The object into which to store the result.
			 * @returns {Cartesian4} A cartesian with the minimum components.
			 */
			static Cartesian4 minimumByComponent(Cartesian4& first, Cartesian4& second) {
				Cartesian4 result;
				result.x = (std::min)(first.x, second.x);
				result.y = (std::min)(first.y, second.y);
				result.z = (std::min)(first.z, second.z);
				result.w = (std::min)(first.w, second.w);
				return result;
			};

			/**
			 * Compares two Cartesians and computes a Cartesian which contains the maximum components of the supplied Cartesians.
			 *
			 * @param {Cartesian4} first A cartesian to compare.
			 * @param {Cartesian4} second A cartesian to compare.
			 * @param {Cartesian4} result The object into which to store the result.
			 * @returns {Cartesian4} A cartesian with the maximum components.
			 */
			static Cartesian4 maximumByComponent(Cartesian4& first, Cartesian4& second) {
				Cartesian4 result;

				result.x = (std::max)(first.x, second.x);
				result.y = (std::max)(first.y, second.y);
				result.z = (std::max)(first.z, second.z);
				result.w = (std::max)(first.w, second.w);

				return result;
			};

			/**
			 * Constrain a value to lie between two values.
			 *
			 * @param {Cartesian4} value The value to clamp.
			 * @param {Cartesian4} min The minimum bound.
			 * @param {Cartesian4} max The maximum bound.
			 * @param {Cartesian4} result The object into which to store the result.
			 * @returns {Cartesian4} The clamped value such that min <= result <= max.
			 */
			static Cartesian4 clamp(Cartesian4& value, Cartesian4& min, Cartesian4& max) {
				auto x = CesiumMath::clamp(value.x, min.x, max.x);
				auto y = CesiumMath::clamp(value.y, min.y, max.y);
				auto z = CesiumMath::clamp(value.z, min.z, max.z);
				auto w = CesiumMath::clamp(value.w, min.w, max.w);
				Cartesian4 result;
				result.x = x;
				result.y = y;
				result.z = z;
				result.w = w;

				return result;
			};

			/**
			 * Computes the provided Cartesian's squared magnitude.
			 *
			 * @param {Cartesian4} cartesian The Cartesian instance whose squared magnitude is to be computed.
			 * @returns {number} The squared magnitude.
			 */
			static double magnitudeSquared(Cartesian4& cartesian) {
				return (
					cartesian.x * cartesian.x +
					cartesian.y * cartesian.y +
					cartesian.z * cartesian.z +
					cartesian.w * cartesian.w
					);
			};

			/**
			 * Computes the Cartesian's magnitude (length).
			 *
			 * @param {Cartesian4} cartesian The Cartesian instance whose magnitude is to be computed.
			 * @returns {number} The magnitude.
			 */
			static double magnitude(Cartesian4& cartesian) {
				return sqrt(Cartesian4::magnitudeSquared(cartesian));
			};

			/**
			 * Computes the 4-space distance between two points.
			 *
			 * @param {Cartesian4} left The first point to compute the distance from.
			 * @param {Cartesian4} right The second point to compute the distance to.
			 * @returns {number} The distance between two points.
			 *
			 * @example
			 * // Returns 1.0
			 * const d = Cesium.Cartesian4::distance(
			 *   new Cesium.Cartesian4(1.0, 0.0, 0.0, 0.0),
			 *   new Cesium.Cartesian4(2.0, 0.0, 0.0, 0.0));
			 */
			static double distance(Cartesian4& left, Cartesian4& right) {
				auto distanceScratch = Cartesian4::subtract(left, right);
				return Cartesian4::magnitude(distanceScratch);
			};

			/**
			 * Computes the squared distance between two points.  Comparing squared distances
			 * using this function is more efficient than comparing distances using {@link Cartesian4#distance}.
			 *
			 * @param {Cartesian4} left The first point to compute the distance from.
			 * @param {Cartesian4} right The second point to compute the distance to.
			 * @returns {number} The distance between two points.
			 *
			 * @example
			 * // Returns 4.0, not 2.0
			 * const d = Cesium.Cartesian4.distance(
			 *   new Cesium.Cartesian4(1.0, 0.0, 0.0, 0.0),
			 *   new Cesium.Cartesian4(3.0, 0.0, 0.0, 0.0));
			 */
			static double distanceSquared(Cartesian4& left, Cartesian4& right) {
				auto distanceScratch = Cartesian4::subtract(left, right);
				return Cartesian4::magnitudeSquared(distanceScratch);
			};

			/**
			 * Computes the normalized form of the supplied Cartesian.
			 *
			 * @param {Cartesian4} cartesian The Cartesian to be normalized.
			 * @param {Cartesian4} result The object onto which to store the result.
			 * @returns {Cartesian4} The modified result parameter.
			 */
			static Cartesian4 normalize(Cartesian4& cartesian) {
				auto magnitude = Cartesian4::magnitude(cartesian);
				Cartesian4 result;
				result.x = cartesian.x / magnitude;
				result.y = cartesian.y / magnitude;
				result.z = cartesian.z / magnitude;
				result.w = cartesian.w / magnitude;

				//>>includeStart('debug', pragmas.debug);
				if (
					CesiumMath::isNaN(result.x) ||
					CesiumMath::isNaN(result.y) ||
					CesiumMath::isNaN(result.z) ||
					CesiumMath::isNaN(result.w)
					) {

				}
				//>>includeEnd('debug');

				return result;
			};

			/**
			 * Computes the dot (scalar) product of two Cartesians.
			 *
			 * @param {Cartesian4} left The first Cartesian.
			 * @param {Cartesian4} right The second Cartesian.
			 * @returns {number} The dot product.
			 */
			static double dot(Cartesian4& left, Cartesian4& right) {
				return (
					left.x * right.x + left.y * right.y + left.z * right.z + left.w * right.w
					);
			};

			/**
			 * Computes the componentwise product of two Cartesians.
			 *
			 * @param {Cartesian4} left The first Cartesian.
			 * @param {Cartesian4} right The second Cartesian.
			 * @param {Cartesian4} result The object onto which to store the result.
			 * @returns {Cartesian4} The modified result parameter.
			 */
			static Cartesian4 multiplyComponents(Cartesian4& left, Cartesian4& right) {
				Cartesian4 result;
				result.x = left.x * right.x;
				result.y = left.y * right.y;
				result.z = left.z * right.z;
				result.w = left.w * right.w;
				return result;
			};

			/**
			 * Computes the componentwise quotient of two Cartesians.
			 *
			 * @param {Cartesian4} left The first Cartesian.
			 * @param {Cartesian4} right The second Cartesian.
			 * @param {Cartesian4} result The object onto which to store the result.
			 * @returns {Cartesian4} The modified result parameter.
			 */
			static Cartesian4 divideComponents(Cartesian4& left, Cartesian4& right) {
				Cartesian4 result;
				result.x = left.x / right.x;
				result.y = left.y / right.y;
				result.z = left.z / right.z;
				result.w = left.w / right.w;
				return result;
			};

			/**
			 * Computes the componentwise sum of two Cartesians.
			 *
			 * @param {Cartesian4} left The first Cartesian.
			 * @param {Cartesian4} right The second Cartesian.
			 * @param {Cartesian4} result The object onto which to store the result.
			 * @returns {Cartesian4} The modified result parameter.
			 */
			static Cartesian4 add(Cartesian4& left, Cartesian4& right) {
				Cartesian4 result;

				result.x = left.x + right.x;
				result.y = left.y + right.y;
				result.z = left.z + right.z;
				result.w = left.w + right.w;
				return result;
			};

			/**
			 * Computes the componentwise difference of two Cartesians.
			 *
			 * @param {Cartesian4} left The first Cartesian.
			 * @param {Cartesian4} right The second Cartesian.
			 * @param {Cartesian4} result The object onto which to store the result.
			 * @returns {Cartesian4} The modified result parameter.
			 */
			static Cartesian4 subtract(Cartesian4& left, Cartesian4& right) {
				Cartesian4 result;
				result.x = left.x - right.x;
				result.y = left.y - right.y;
				result.z = left.z - right.z;
				result.w = left.w - right.w;
				return result;
			};

			/**
			 * Multiplies the provided Cartesian componentwise by the provided scalar.
			 *
			 * @param {Cartesian4} cartesian The Cartesian to be scaled.
			 * @param {number} scalar The scalar to multiply with.
			 * @param {Cartesian4} result The object onto which to store the result.
			 * @returns {Cartesian4} The modified result parameter.
			 */
			static Cartesian4 multiplyByScalar(Cartesian4 cartesian, double scalar) {
				Cartesian4 result;
				result.x = cartesian.x * scalar;
				result.y = cartesian.y * scalar;
				result.z = cartesian.z * scalar;
				result.w = cartesian.w * scalar;
				return result;
			};

			/**
			 * Divides the provided Cartesian componentwise by the provided scalar.
			 *
			 * @param {Cartesian4} cartesian The Cartesian to be divided.
			 * @param {number} scalar The scalar to divide by.
			 * @param {Cartesian4} result The object onto which to store the result.
			 * @returns {Cartesian4} The modified result parameter.
			 */
			static Cartesian4 divideByScalar(Cartesian4 cartesian, double scalar) {
				Cartesian4 result;
				result.x = cartesian.x / scalar;
				result.y = cartesian.y / scalar;
				result.z = cartesian.z / scalar;
				result.w = cartesian.w / scalar;
				return result;
			};

			/**
			 * Negates the provided Cartesian.
			 *
			 * @param {Cartesian4} cartesian The Cartesian to be negated.
			 * @param {Cartesian4} result The object onto which to store the result.
			 * @returns {Cartesian4} The modified result parameter.
			 */
			static Cartesian4 negate(Cartesian4 cartesian) {
				Cartesian4 result;

				result.x = -cartesian.x;
				result.y = -cartesian.y;
				result.z = -cartesian.z;
				result.w = -cartesian.w;
				return result;
			};

			/**
			 * Computes the absolute value of the provided Cartesian.
			 *
			 * @param {Cartesian4} cartesian The Cartesian whose absolute value is to be computed.
			 * @param {Cartesian4} result The object onto which to store the result.
			 * @returns {Cartesian4} The modified result parameter.
			 */
			static Cartesian4 abs(Cartesian4 cartesian) {
				Cartesian4 result;
				result.x = std::abs(cartesian.x);
				result.y = std::abs(cartesian.y);
				result.z = std::abs(cartesian.z);
				result.w = std::abs(cartesian.w);
				return result;
			};

			/**
			 * Computes the linear interpolation or extrapolation at t using the provided cartesians.
			 *
			 * @param {Cartesian4} start The value corresponding to t at 0.0.
			 * @param {Cartesian4}end The value corresponding to t at 1.0.
			 * @param {number} t The point along t at which to interpolate.
			 * @param {Cartesian4} result The object onto which to store the result.
			 * @returns {Cartesian4} The modified result parameter.
			 */
			static Cartesian4 lerp(Cartesian4& start, Cartesian4& end, double t) {
				auto lerpScratch = Cartesian4::multiplyByScalar(end, t);
				auto result = Cartesian4::multiplyByScalar(start, 1.0 - t);
				return Cartesian4::add(lerpScratch, result);
			};

			/**
			 * Returns the axis that is most orthogonal to the provided Cartesian.
			 *
			 * @param {Cartesian4} cartesian The Cartesian on which to find the most orthogonal axis.
			 * @param {Cartesian4} result The object onto which to store the result.
			 * @returns {Cartesian4} The most orthogonal axis.
			 */
			static Cartesian4 mostOrthogonalAxis(Cartesian4& cartesian) {
				auto f = Cartesian4::normalize(cartesian);
				f = Cartesian4::abs(f);
				Cartesian4 result;
				if (f.x <= f.y) {
					if (f.x <= f.z) {
						if (f.x <= f.w) {
							result = Cartesian4::UNIT_X;
						}
						else {
							result = Cartesian4::UNIT_W;
						}
					}
					else if (f.z <= f.w) {
						result = Cartesian4::UNIT_Z;
					}
					else {
						result = Cartesian4::UNIT_W;
					}
				}
				else if (f.y <= f.z) {
					if (f.y <= f.w) {
						result = Cartesian4::UNIT_Y;
					}
					else {
						result = Cartesian4::UNIT_W;
					}
				}
				else if (f.z <= f.w) {
					result = Cartesian4::UNIT_Z;
				}
				else {
					result = Cartesian4::UNIT_W;
				}

				return result;
			};

			/**
			 * Compares the provided Cartesians componentwise and returns
			 * <code>true</code> if they are equal, <code>false</code> otherwise.
			 *
			 * @param {Cartesian4} [left] The first Cartesian.
			 * @param {Cartesian4} [right] The second Cartesian.
			 * @returns {boolean} <code>true</code> if left and right are equal, <code>false</code> otherwise.
			 */
			static bool equals(Cartesian4 left, Cartesian4 right) {
				return (
					left.x == right.x &&
					left.y == right.y &&
					left.z == right.z &&
					left.w == right.w
					);
			};

			/**
			 * @private
			 */
			static bool equalsArray(Cartesian4& cartesian, DoubleVector array1, size_t offset) {
				return (
					cartesian.x == array1[offset] &&
					cartesian.y == array1[offset + 1] &&
					cartesian.z == array1[offset + 2] &&
					cartesian.w == array1[offset + 3]
					);
			};

			/**
			 * Compares the provided Cartesians componentwise and returns
			 * <code>true</code> if they pass an absolute or relative tolerance test,
			 * <code>false</code> otherwise.
			 *
			 * @param {Cartesian4} [left] The first Cartesian.
			 * @param {Cartesian4} [right] The second Cartesian.
			 * @param {number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.
			 * @param {number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
			 * @returns {boolean} <code>true</code> if left and right are within the provided epsilon, <code>false</code> otherwise.
			 */
			static bool equalsEpsilon(
				Cartesian4& left,
				Cartesian4& right,
				double relativeEpsilon = 0.0,
				double absoluteEpsilon = 0.0
			) {
				return (
					CesiumMath::equalsEpsilon(
						left.x,
						right.x,
						relativeEpsilon,
						absoluteEpsilon
					) &&
					CesiumMath::equalsEpsilon(
						left.y,
						right.y,
						relativeEpsilon,
						absoluteEpsilon
					) &&
					CesiumMath::equalsEpsilon(
						left.z,
						right.z,
						relativeEpsilon,
						absoluteEpsilon
					) &&
					CesiumMath::equalsEpsilon(
						left.w,
						right.w,
						relativeEpsilon,
						absoluteEpsilon
					)
					);
			};

			/**
			 * An immutable Cartesian4 instance initialized to (0.0, 0.0, 0.0, 0.0).
			 *
			 * @type {Cartesian4}
			 * @constant
			 */
			const static Cartesian4 ZERO;

			/**
			 * An immutable Cartesian4 instance initialized to (1.0, 1.0, 1.0, 1.0).
			 *
			 * @type {Cartesian4}
			 * @constant
			 */
			const static Cartesian4 ONE;

			/**
			 * An immutable Cartesian4 instance initialized to (1.0, 0.0, 0.0, 0.0).
			 *
			 * @type {Cartesian4}
			 * @constant
			 */
			const static Cartesian4 UNIT_X;

			/**
			 * An immutable Cartesian4 instance initialized to (0.0, 1.0, 0.0, 0.0).
			 *
			 * @type {Cartesian4}
			 * @constant
			 */
			const static Cartesian4 UNIT_Y;

			/**
			 * An immutable Cartesian4 instance initialized to (0.0, 0.0, 1.0, 0.0).
			 *
			 * @type {Cartesian4}
			 * @constant
			 */
			const static Cartesian4 UNIT_Z;

			/**
			 * An immutable Cartesian4 instance initialized to (0.0, 0.0, 0.0, 1.0).
			 *
			 * @type {Cartesian4}
			 * @constant
			 */
			const static Cartesian4 UNIT_W;

			/**
			 * Compares this Cartesian against the provided Cartesian componentwise and returns
			 * <code>true</code> if they are equal, <code>false</code> otherwise.
			 *
			 * @param {Cartesian4} [right] The right hand side Cartesian.
			 * @returns {boolean} <code>true</code> if they are equal, <code>false</code> otherwise.
			 */
			bool equals(Cartesian4& right) {
				return Cartesian4::equals(*this, right);
			};

			/**
			 * Compares this Cartesian against the provided Cartesian componentwise and returns
			 * <code>true</code> if they pass an absolute or relative tolerance test,
			 * <code>false</code> otherwise.
			 *
			 * @param {Cartesian4} [right] The right hand side Cartesian.
			 * @param {number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.
			 * @param {number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.
			 * @returns {boolean} <code>true</code> if they are within the provided epsilon, <code>false</code> otherwise.
			 */
			bool equalsEpsilon(
				Cartesian4& right,
				double relativeEpsilon = 0.0,
				double absoluteEpsilon = 0.0
			) {
				return Cartesian4::equalsEpsilon(
					*this,
					right,
					relativeEpsilon,
					absoluteEpsilon
				);
			};

			/**
			 * Creates a string representing this Cartesian in the format '(x, y, z, w)'.
			 *
			 * @returns {string} A string representing the provided Cartesian in the format '(x, y, z, w)'.
			 */
			String toString() {

				return str_format("%f,%f,%f,%f", x, y, z, w);
			};

			// scratchU8Array and scratchF32Array are views into the same buffer
			//Uint8Vector scratchU8Array = new Uint8Array(scratchF32Array.buffer);
			//Uint32Vector testU32 = { 0x11223344 };
			//Uint8Vector testU8 = new Uint8Array(testU32.buffer);
			//const static bool littleEndian = testU8[0] == 0x44;
			const static bool littleEndian = true;

			/**
			 * Packs an arbitrary floating point value to 4 values representable using uint8.
			 *
			 * @param {number} value A floating point number.
			 * @param {Cartesian4} [result] The Cartesian4 that will contain the packed float.
			 * @returns {Cartesian4} A Cartesian4 representing the float packed to values in x, y, z, and w.
			 */
			static Cartesian4 packFloat(float value) {
				Cartesian4 result;

				std::vector<float> scratchF32Array = { value };

				Uint8Vector scratchU8Array;
				scratchU8Array.resize(4);

				memcpy(&scratchU8Array[0], &scratchF32Array[0], 4);

				//Uint8Vector scratchU8Array = new Uint8Array(scratchF32Array.buffer);
				if (littleEndian) {
					result.x = scratchU8Array[0];
					result.y = scratchU8Array[1];
					result.z = scratchU8Array[2];
					result.w = scratchU8Array[3];
				}
				else {
					// convert from big-endian to little-endian
					result.x = scratchU8Array[3];
					result.y = scratchU8Array[2];
					result.z = scratchU8Array[1];
					result.w = scratchU8Array[0];
				}
				return result;
			};

			/**
			 * Unpacks a float packed using Cartesian4.packFloat.
			 *
			 * @param {Cartesian4} packedFloat A Cartesian4 containing a float packed to 4 values representable using uint8.
			 * @returns {number} The unpacked float.
			 * @private
			 */
			static Cartesian4 unpackFloat(Cartesian4 packedFloat) {

				Uint8Vector scratchU8Array;
				scratchU8Array.resize(4);



				// scratchU8Array and scratchF32Array are views into the same buffer
				if (littleEndian) {
					scratchU8Array[0] = packedFloat.x;
					scratchU8Array[1] = packedFloat.y;
					scratchU8Array[2] = packedFloat.z;
					scratchU8Array[3] = packedFloat.w;
				}
				else {
					// convert from little-endian to big-endian
					scratchU8Array[0] = packedFloat.w;
					scratchU8Array[1] = packedFloat.z;
					scratchU8Array[2] = packedFloat.y;
					scratchU8Array[3] = packedFloat.x;
				}

				std::vector<float> scratchF32Array = { 0.0 };
				memcpy(&scratchF32Array[0], &scratchU8Array[0], 4);

				return scratchF32Array[0];
			};
		};
	}
}

#endif

